From: iap10@labyrinth.cl.cam.ac.uk Date: Thu, 24 Jun 2004 10:50:33 +0000 (+0000) Subject: bitkeeper revision 1.921.1.1 (40dab1f9AV7eQ2rrrWjdce8ozia3XQ) X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~18109^2 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=24090828bdd7695c202ece69bc75723963d9dd5f;p=xen.git bitkeeper revision 1.921.1.1 (40dab1f9AV7eQ2rrrWjdce8ozia3XQ) add more stats collection to migration, prepare for NGIO fixup. --- diff --git a/tools/xc/lib/xc.h b/tools/xc/lib/xc.h index 3423c4ec46..b2c20eb122 100644 --- a/tools/xc/lib/xc.h +++ b/tools/xc/lib/xc.h @@ -35,6 +35,14 @@ typedef struct { unsigned long max_memkb; } xc_dominfo_t; +typedef struct xc_shadow_control_stats_st +{ + unsigned long fault_count; + unsigned long dirty_count; + unsigned long dirty_net_count; + unsigned long dirty_block_count; +} xc_shadow_control_stats_t; + int xc_domain_create(int xc_handle, unsigned int mem_kb, const char *name, @@ -60,8 +68,7 @@ int xc_shadow_control(int xc_handle, unsigned int sop, unsigned long *dirty_bitmap, unsigned long pages, - unsigned long *fault_count, - unsigned long *dirty_count); + xc_shadow_control_stats_t *stats); #define XCFLAGS_VERBOSE 1 diff --git a/tools/xc/lib/xc_domain.c b/tools/xc/lib/xc_domain.c index dd8b4ec35f..d8ec3e1677 100644 --- a/tools/xc/lib/xc_domain.c +++ b/tools/xc/lib/xc_domain.c @@ -113,8 +113,7 @@ int xc_shadow_control(int xc_handle, unsigned int sop, unsigned long *dirty_bitmap, unsigned long pages, - unsigned long *fault_count, - unsigned long *dirty_count) + xc_shadow_control_stats_t *stats ) { int rc; dom0_op_t op; @@ -126,8 +125,8 @@ int xc_shadow_control(int xc_handle, rc = do_dom0_op(xc_handle, &op); - if(fault_count) *fault_count = op.u.shadow_control.fault_count; - if(dirty_count) *dirty_count = op.u.shadow_control.dirty_count; + if(stats) memcpy(stats, &op.u.shadow_control.stats, + sizeof(xc_shadow_control_stats_t)); if ( rc == 0 ) return op.u.shadow_control.pages; diff --git a/tools/xc/lib/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c index 4913a8527f..97ad5fdb4a 100644 --- a/tools/xc/lib/xc_linux_save.c +++ b/tools/xc/lib/xc_linux_save.c @@ -144,14 +144,22 @@ static long long tv_to_us( struct timeval *new ) return (new->tv_sec * 1000000) + new->tv_usec; } -static long long tvdelta( struct timeval *new, struct timeval *old ) +static long long llgettimeofday() +{ + struct timeval now; + gettimeofday(&now, NULL); + return tv_to_us(&now); +} + +static long long tv_delta( struct timeval *new, struct timeval *old ) { return ((new->tv_sec - old->tv_sec)*1000000 ) + (new->tv_usec - old->tv_usec); } -static int track_cpu_usage( int xc_handle, u64 domid, int faults, - int pages_sent, int pages_dirtied, int print ) +static int print_stats( int xc_handle, u64 domid, + int pages_sent, xc_shadow_control_stats_t *stats, + int print ) { static struct timeval wall_last; static long long d0_cpu_last; @@ -162,7 +170,6 @@ static int track_cpu_usage( int xc_handle, u64 domid, int faults, long long d0_cpu_now, d0_cpu_delta; long long d1_cpu_now, d1_cpu_delta; - gettimeofday(&wall_now, NULL); d0_cpu_now = xc_domain_get_cpu_usage( xc_handle, 0 )/1000; @@ -173,7 +180,7 @@ static int track_cpu_usage( int xc_handle, u64 domid, int faults, printf("ARRHHH!!\n"); } - wall_delta = tvdelta(&wall_now,&wall_last)/1000; + wall_delta = tv_delta(&wall_now,&wall_last)/1000; if ( wall_delta == 0 ) wall_delta = 1; @@ -186,7 +193,7 @@ static int track_cpu_usage( int xc_handle, u64 domid, int faults, (int)((d0_cpu_delta*100)/wall_delta), (int)((d1_cpu_delta*100)/wall_delta), (int)((pages_sent*PAGE_SIZE*8)/(wall_delta*1000)), - (int)((pages_dirtied*PAGE_SIZE*8)/(wall_delta*1000)) + (int)((stats->dirty_count*PAGE_SIZE*8)/(wall_delta*1000)) ); d0_cpu_last = d0_cpu_now; @@ -197,6 +204,44 @@ static int track_cpu_usage( int xc_handle, u64 domid, int faults, } +static int analysis_phase( int xc_handle, u64 domid, + int nr_pfns, unsigned long *arr ) +{ + long long start, now; + xc_shadow_control_stats_t stats; + + start = llgettimeofday(); + + while(0) + { + int i; + + xc_shadow_control( xc_handle, domid, + DOM0_SHADOW_CONTROL_OP_CLEAN2, + arr, nr_pfns, NULL); + printf("#Flush\n"); + for(i=0;i<100;i++) + { + usleep(10000); + now = llgettimeofday(); + xc_shadow_control( xc_handle, domid, + DOM0_SHADOW_CONTROL_OP_PEEK, + NULL, 0, &stats); + + printf("now= %lld faults= %ld dirty= %ld dirty_net= %ld dirty_block= %ld\n", + ((now-start)+500)/1000, + stats.fault_count, stats.dirty_count, + stats.dirty_net_count, stats.dirty_block_count ); + + } + + + } + + + return -1; +} + int xc_linux_save(int xc_handle, u64 domid, unsigned int flags, @@ -210,7 +255,6 @@ int xc_linux_save(int xc_handle, int live = flags & XCFLAGS_LIVE; int debug = flags & XCFLAGS_DEBUG; int sent_last_iter, sent_this_iter, skip_this_iter; - unsigned long dirtied_this_iter, faults_this_iter; /* Important tuning parameters */ int max_iters = 29; // limit us to 30 times round loop @@ -261,6 +305,8 @@ int xc_linux_save(int xc_handle, - to skip this iteration because already dirty; - to fixup by sending at the end if not already resent; */ unsigned long *to_send, *to_skip, *to_fix; + + xc_shadow_control_stats_t stats; int needed_to_fix = 0; int total_sent = 0; @@ -374,7 +420,7 @@ int xc_linux_save(int xc_handle, { if ( xc_shadow_control( xc_handle, domid, DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY, - NULL, 0, NULL, NULL ) < 0 ) + NULL, 0, NULL ) < 0 ) { ERROR("Couldn't enable shadow mode"); goto out; @@ -392,6 +438,9 @@ int xc_linux_save(int xc_handle, else last_iter = 1; + /* calculate the power of 2 order of nr_pfns, e.g. + 15->4 16->4 17->5 */ + for( i=nr_pfns-1, order_nr=0; i ; i>>=1, order_nr++ ); /* Setup to_send bitmap */ { @@ -425,11 +474,7 @@ int xc_linux_save(int xc_handle, } - /* calculate the power of 2 order of nr_pfns, e.g. - 15->4 16->4 17->5 */ - for( i=nr_pfns-1, order_nr=0; i ; i>>=1, order_nr++ ); - -printf("nr_pfns=%d order_nr=%d\n",nr_pfns, order_nr); + analysis_phase( xc_handle, domid, nr_pfns, to_skip ); /* We want zeroed memory so use calloc rather than malloc. */ pfn_type = calloc(BATCH_SIZE, sizeof(unsigned long)); @@ -484,7 +529,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfns, order_nr); goto out; } - track_cpu_usage( xc_handle, domid, 0, 0, 0, 0 ); + print_stats( xc_handle, domid, 0, &stats, 0 ); /* Now write out each data page, canonicalising page tables as we go... */ @@ -516,7 +561,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfns, order_nr); if ( !last_iter && xc_shadow_control(xc_handle, domid, DOM0_SHADOW_CONTROL_OP_PEEK, - to_skip, nr_pfns, NULL, NULL) != nr_pfns ) + to_skip, nr_pfns, NULL) != nr_pfns ) { ERROR("Error peeking shadow bitmap"); goto out; @@ -722,7 +767,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfns, order_nr); if ( last_iter ) { - track_cpu_usage( xc_handle, domid, 0, sent_this_iter, 0, 1); + print_stats( xc_handle, domid, sent_this_iter, &stats, 1); verbose_printf("Total pages sent= %d (%.2fx)\n", total_sent, ((float)total_sent)/nr_pfns ); @@ -732,7 +777,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfns, order_nr); if ( debug && last_iter ) { int minusone = -1; - memset( to_send, 0xff, nr_pfns/8 ); + memset( to_send, 0xff, (nr_pfns+8)/8 ); debug = 0; printf("Entering debug resend-all mode\n"); @@ -766,8 +811,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfns, order_nr); if ( xc_shadow_control( xc_handle, domid, DOM0_SHADOW_CONTROL_OP_CLEAN2, - to_send, nr_pfns, &faults_this_iter, - &dirtied_this_iter) != nr_pfns ) + to_send, nr_pfns, &stats ) != nr_pfns ) { ERROR("Error flushing shadow PT"); goto out; @@ -775,9 +819,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfns, order_nr); sent_last_iter = sent_this_iter; - //dirtied_this_iter = count_bits( nr_pfns, to_send ); - track_cpu_usage( xc_handle, domid, faults_this_iter, - sent_this_iter, dirtied_this_iter, 1); + print_stats( xc_handle, domid, sent_this_iter, &stats, 1); } diff --git a/tools/xc/py/Xc.c b/tools/xc/py/Xc.c index d2a291e4c8..1455096686 100644 --- a/tools/xc/py/Xc.c +++ b/tools/xc/py/Xc.c @@ -1296,7 +1296,7 @@ static PyObject *pyxc_shadow_control(PyObject *self, &dom, &op) ) return NULL; - if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL, NULL) < 0 ) + if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 ) return PyErr_SetFromErrno(xc_error); Py_INCREF(zero); diff --git a/xen/common/shadow.c b/xen/common/shadow.c index d9e4d9aef8..63280ba2a0 100644 --- a/xen/common/shadow.c +++ b/xen/common/shadow.c @@ -48,7 +48,7 @@ fault handler spinning waiting to grab the shadow lock. It may have intterupts disabled, hence we can't use the normal flush_tlb_cpu mechanism. -For the moment, we have a grim hace whereby the spinlock in the shadow +For the moment, we have a grim race whereby the spinlock in the shadow fault handler is actually a try lock, in a loop with a helper for the tlb flush code. @@ -379,6 +379,17 @@ static int shadow_mode_table_op( struct task_struct *p, __scan_shadow_table( m, TABLE_OP_FREE_L1 ); send_bitmap: + sc->stats.fault_count = p->mm.shadow_fault_count; + sc->stats.dirty_count = p->mm.shadow_dirty_count; + sc->stats.dirty_net_count = p->mm.shadow_dirty_net_count; + sc->stats.dirty_block_count = p->mm.shadow_dirty_block_count; + + p->mm.shadow_fault_count = 0; + p->mm.shadow_dirty_count = 0; + p->mm.shadow_dirty_net_count = 0; + p->mm.shadow_dirty_block_count = 0; + + sc->pages = p->tot_pages; if( p->tot_pages > sc->pages || !sc->dirty_bitmap || !p->mm.shadow_dirty_bitmap ) @@ -387,12 +398,6 @@ static int shadow_mode_table_op( struct task_struct *p, goto out; } - sc->fault_count = p->mm.shadow_fault_count; - sc->dirty_count = p->mm.shadow_dirty_count; - p->mm.shadow_fault_count = 0; - p->mm.shadow_dirty_count = 0; - - sc->pages = p->tot_pages; #define chunk (8*1024) // do this in 1KB chunks for L1 cache @@ -428,6 +433,11 @@ static int shadow_mode_table_op( struct task_struct *p, case DOM0_SHADOW_CONTROL_OP_PEEK: { int i; + + sc->stats.fault_count = p->mm.shadow_fault_count; + sc->stats.dirty_count = p->mm.shadow_dirty_count; + sc->stats.dirty_net_count = p->mm.shadow_dirty_net_count; + sc->stats.dirty_block_count = p->mm.shadow_dirty_block_count; if( p->tot_pages > sc->pages || !sc->dirty_bitmap || !p->mm.shadow_dirty_bitmap ) @@ -724,7 +734,7 @@ int shadow_fault( unsigned long va, long error_code ) int i; sl1pfn_info = alloc_shadow_page( ¤t->mm ); sl1pfn_info->type_and_flags = PGT_l1_page_table; - + sl1pfn = sl1pfn_info - frame_table; SH_VVLOG("4a: l1 not shadowed ( %08lx )",sl1pfn); diff --git a/xen/drivers/block/xen_block.c b/xen/drivers/block/xen_block.c index 6901262cb8..0f80501b83 100644 --- a/xen/drivers/block/xen_block.c +++ b/xen/drivers/block/xen_block.c @@ -364,7 +364,8 @@ static void unlock_buffer(unsigned long buffer, struct task_struct *p = frame_table[pfn].u.domain; if( p->mm.shadow_mode == SHM_logdirty ) - mark_dirty( &p->mm, pfn ); + if( mark_dirty( &p->mm, pfn ) ) + p->mm.shadow_dirty_block_count++; if ( writeable_buffer ) diff --git a/xen/include/asm-i386/processor.h b/xen/include/asm-i386/processor.h index b1eab99d56..5edc743eda 100644 --- a/xen/include/asm-i386/processor.h +++ b/xen/include/asm-i386/processor.h @@ -465,6 +465,8 @@ struct mm_struct { unsigned int shadow_page_count; unsigned int shadow_fault_count; unsigned int shadow_dirty_count; + unsigned int shadow_dirty_net_count; + unsigned int shadow_dirty_block_count; /* Current LDT details. */ diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index 6273878d16..effb7d1287 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -245,10 +245,20 @@ typedef struct dom0_sched_id_st #define DOM0_SHADOW_CONTROL_OP_OFF 0 #define DOM0_SHADOW_CONTROL_OP_ENABLE_TEST 1 #define DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY 2 +#define DOM0_SHADOW_CONTROL_OP_ENABLE_TRANSLATE 3 #define DOM0_SHADOW_CONTROL_OP_FLUSH 10 /* table ops */ #define DOM0_SHADOW_CONTROL_OP_CLEAN 11 #define DOM0_SHADOW_CONTROL_OP_PEEK 12 #define DOM0_SHADOW_CONTROL_OP_CLEAN2 13 + +typedef struct dom0_shadow_control_stats_st +{ + unsigned long fault_count; + unsigned long dirty_count; + unsigned long dirty_net_count; + unsigned long dirty_block_count; +} dom0_shadow_control_stats_t; + typedef struct dom0_shadow_control_st { /* IN variables. */ @@ -258,8 +268,7 @@ typedef struct dom0_shadow_control_st /* IN/OUT variables */ unsigned long pages; // size of buffer, updated with actual size /* OUT varaibles */ - unsigned long fault_count; - unsigned long dirty_count; + dom0_shadow_control_stats_t stats; } dom0_shadow_control_t; #define DOM0_SETDOMAINNAME 26 diff --git a/xen/include/xen/shadow.h b/xen/include/xen/shadow.h index 1597e1feb2..83dc29f00d 100644 --- a/xen/include/xen/shadow.h +++ b/xen/include/xen/shadow.h @@ -17,8 +17,9 @@ /* Shadow PT operation mode : shadowmode variable in mm_struct */ #define SHM_test (1) /* just run domain on shadow PTs */ #define SHM_logdirty (2) /* log pages that are dirtied */ -#define SHM_cow (3) /* copy on write all dirtied pages */ -#define SHM_translate (4) /* lookup machine pages in translation table */ +#define SHM_translate (3) /* lookup machine pages in translation table */ +//#define SHM_cow (4) /* copy on write all dirtied pages */ + #define shadow_linear_pg_table ((l1_pgentry_t *)SH_LINEAR_PT_VIRT_START) #define shadow_linear_l2_table ((l2_pgentry_t *)(SH_LINEAR_PT_VIRT_START+(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT-L1_PAGETABLE_SHIFT)))) @@ -76,9 +77,10 @@ printk("DOM%lld: (file=shadow.c, line=%d) " _f "\n", \ /************************************************************************/ - static inline void __mark_dirty( struct mm_struct *m, unsigned int mfn ) +static inline int __mark_dirty( struct mm_struct *m, unsigned int mfn ) { unsigned int pfn; + int rc = 0; ASSERT(spin_is_locked(&m->shadow_lock)); @@ -90,17 +92,19 @@ printk("DOM%lld: (file=shadow.c, line=%d) " _f "\n", \ really part of the domain's psuedo-physical memory map e.g. the shared info frame. Nothing to do here... */ - if ( unlikely(pfn & 0x80000000U) ) return; + if ( unlikely(pfn & 0x80000000U) ) return rc; ASSERT(m->shadow_dirty_bitmap); if( likely(pfnshadow_dirty_bitmap_size) ) { - /* These updates occur with mm.shadow_lock held, so use - (__) version of test_and_set */ - if( ! __test_and_set_bit( pfn, m->shadow_dirty_bitmap ) ) - { - m->shadow_dirty_count++; - } + /* These updates occur with mm.shadow_lock held, so use + (__) version of test_and_set */ + if( __test_and_set_bit( pfn, m->shadow_dirty_bitmap ) == 0 ) + { + // if we set it + m->shadow_dirty_count++; + rc = 1; + } } else { @@ -113,17 +117,20 @@ printk("DOM%lld: (file=shadow.c, line=%d) " _f "\n", \ frame_table[mfn].type_and_flags ); //show_traceX(); } - + + return rc; } -static inline void mark_dirty( struct mm_struct *m, unsigned int mfn ) +static inline int mark_dirty( struct mm_struct *m, unsigned int mfn ) { + int rc; ASSERT(local_irq_is_enabled()); //if(spin_is_locked(&m->shadow_lock)) printk("+"); spin_lock(&m->shadow_lock); - __mark_dirty( m, mfn ); + rc = __mark_dirty( m, mfn ); spin_unlock(&m->shadow_lock); + return rc; } diff --git a/xen/net/dev.c b/xen/net/dev.c index 909e586b53..4a3088e1bf 100644 --- a/xen/net/dev.c +++ b/xen/net/dev.c @@ -567,7 +567,10 @@ void deliver_packet(struct sk_buff *skb, net_vif_t *vif) /* if in shadow mode, mark the buffer as dirty */ if( p->mm.shadow_mode == SHM_logdirty ) - mark_dirty( &p->mm, (new_page-frame_table) ); + { + if( mark_dirty( &p->mm, (new_page-frame_table) ) ) + p->mm.shadow_dirty_net_count++; + } /* Updates must happen before releasing the descriptor. */ smp_wmb(); @@ -2269,16 +2272,6 @@ long flush_bufs_for_vif(net_vif_t *vif) if( p->mm.shadow_mode == SHM_logdirty ) { mark_dirty( &p->mm, rx->pte_ptr>>PAGE_SHIFT ); -#if 0 - mark_dirty( &p->mm, rx->buf_pfn ); // XXXXXXX debug - - { - unsigned long * p = map_domain_mem( rx->buf_pfn<